from fastapi import APIRouter, HTTPException, UploadFile, File, Form
from pydantic import BaseModel, validator
import os
from fastapi.responses import JSONResponse
import random
import string
import re
import json
import pandas as pd
from io import BytesIO
import tempfile

router_html_real = APIRouter()

# 定义请求体模型
class HTMLRequest(BaseModel):
    content: str
    filename: str = None
    
    @validator('content')
    def validate_html_content(cls, v):
        # 检查是否为有效的HTML内容
        if not cls.is_valid_html(v):
            raise ValueError("无效的HTML内容，必须包含基本的HTML标记")
        return v
    
    @staticmethod
    def is_valid_html(content):
        # 简单检查是否包含基本的HTML标签
        html_pattern = re.compile(r'<html.*?>.*?</html>', re.IGNORECASE | re.DOTALL)
        body_pattern = re.compile(r'<body.*?>.*?</body>', re.IGNORECASE | re.DOTALL)
        head_pattern = re.compile(r'<head.*?>.*?</head>', re.IGNORECASE | re.DOTALL)
        
        return bool(html_pattern.search(content) or body_pattern.search(content) or head_pattern.search(content))

# 定义链接模型
class LinkItem(BaseModel):
    url: str
    description: str

class LinkList(BaseModel):
    links: list[LinkItem]

# 定义主页导航链接模型
class NavLink(BaseModel):
    title: str
    description: str
    url: str

class NavLinkList(BaseModel):
    links: list[NavLink]

@router_html_real.post("/create_html")
async def create_html_file(request: HTMLRequest):
    # 获取静态文件目录
    static_dir = "static"
    
    # 确保文件名有效
    if request.filename:
        filename = request.filename
        # 确保文件名有.html后缀
        if not filename.endswith('.html'):
            filename += '.html'
    else:
        # 生成随机文件名
        random_str = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
        filename = f"html_{random_str}.html"
    
    # 检查文件是否已存在
    file_path = os.path.join(static_dir, filename)
    file_exists = False
    original_filename = filename
    
    if os.path.exists(file_path):
        file_exists = True
        # 如果文件已存在，添加随机数字到文件名
        name_without_ext = filename.rsplit('.', 1)[0]
        random_num = random.randint(1, 999)
        filename = f"{name_without_ext}_{random_num}.html"
        file_path = os.path.join(static_dir, filename)
    
    try:
        # 写入HTML内容到文件
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(request.content)
        
        response_data = {
            "message": "HTML文件创建成功", 
            "filename": filename, 
            "path": f"/static/{filename}",
            "file_exists": file_exists
        }
        
        if file_exists:
            response_data["original_filename"] = original_filename
        
        return JSONResponse(
            content=response_data,
            status_code=200
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"创建HTML文件失败: {str(e)}")

@router_html_real.get("/list_html_files")
async def list_html_files():
    """获取static目录下所有的HTML文件列表"""
    try:
        static_dir = "static"
        files = []
        
        # 确保目录存在
        if not os.path.exists(static_dir):
            return JSONResponse(
                content={"message": "静态文件目录不存在", "files": []},
                status_code=200
            )
        
        # 获取所有html文件
        for file in os.listdir(static_dir):
            if file.endswith('.html'):
                file_path = f"/static/{file}"
                files.append({
                    "name": file,
                    "path": file_path
                })
        
        return JSONResponse(
            content={"files": files},
            status_code=200
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取HTML文件列表失败: {str(e)}")

# 链接保存文件路径
LINKS_FILE = "static/data/links.json"
# 主页导航链接保存文件路径
NAV_LINKS_FILE = "static/data/nav_links.json"

# 确保数据目录存在
def ensure_data_dir():
    os.makedirs(os.path.dirname(LINKS_FILE), exist_ok=True)

# 从文件加载链接
def load_links_from_file():
    ensure_data_dir()
    if os.path.exists(LINKS_FILE):
        try:
            with open(LINKS_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception:
            return []
    return []

# 保存链接到文件
def save_links_to_file(links):
    ensure_data_dir()
    with open(LINKS_FILE, 'w', encoding='utf-8') as f:
        json.dump(links, f, ensure_ascii=False, indent=2)

# 从文件加载主页导航链接
def load_nav_links_from_file():
    ensure_data_dir()
    if os.path.exists(NAV_LINKS_FILE):
        try:
            with open(NAV_LINKS_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception:
            return []
    return []

# 保存主页导航链接到文件
def save_nav_links_to_file(links):
    ensure_data_dir()
    with open(NAV_LINKS_FILE, 'w', encoding='utf-8') as f:
        json.dump(links, f, ensure_ascii=False, indent=2)

@router_html_real.get("/links")
async def get_links():
    """获取保存的链接列表"""
    try:
        links = load_links_from_file()
        return JSONResponse(content={"links": links})
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取链接列表失败: {str(e)}")

@router_html_real.post("/links")
async def save_links(link_list: LinkList):
    """保存链接列表"""
    try:
        links = [{"url": link.url, "description": link.description} for link in link_list.links]
        save_links_to_file(links)
        return JSONResponse(content={"message": "链接保存成功", "count": len(links)})
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"保存链接失败: {str(e)}")

@router_html_real.get("/nav_links")
async def get_nav_links():
    """获取保存的主页导航链接列表"""
    try:
        links = load_nav_links_from_file()
        return JSONResponse(content={"links": links})
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取导航链接列表失败: {str(e)}")

@router_html_real.post("/nav_links")
async def save_nav_links(link_list: NavLinkList):
    """保存主页导航链接列表"""
    try:
        links = [{"title": link.title, "description": link.description, "url": link.url} for link in link_list.links]
        save_nav_links_to_file(links)
        return JSONResponse(content={"message": "导航链接保存成功", "count": len(links)})
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"保存导航链接失败: {str(e)}")

# 表格数据保存文件路径
TABLE_DATA_FILE = "static/data/table_data.json"

# 从文件加载表格数据
def load_table_data_from_file():
    ensure_data_dir()
    if os.path.exists(TABLE_DATA_FILE):
        try:
            with open(TABLE_DATA_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception:
            return {}
    return {}

# 保存表格数据到文件
def save_table_data_to_file(tables):
    ensure_data_dir()
    with open(TABLE_DATA_FILE, 'w', encoding='utf-8') as f:
        json.dump(tables, f, ensure_ascii=False, indent=2)

# 表格数据模型
class TableData(BaseModel):
    tables: dict

@router_html_real.get("/table_data")
async def get_table_data():
    """获取保存的表格数据"""
    try:
        tables = load_table_data_from_file()
        return JSONResponse(content={"tables": tables})
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取表格数据失败: {str(e)}")

@router_html_real.post("/table_data")
async def save_table_data(data: TableData):
    """保存表格数据"""
    try:
        save_table_data_to_file(data.tables)
        return JSONResponse(content={"message": "表格数据保存成功", "count": len(data.tables)})
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"保存表格数据失败: {str(e)}")

# Excel文件处理
@router_html_real.post("/upload_excel")
async def upload_excel(file: UploadFile = File(...)):
    """上传Excel文件并返回所有表名"""
    try:
        # 检查文件类型
        if not file.filename.endswith(('.xlsx', '.xls')):
            raise HTTPException(status_code=400, detail="只接受.xlsx或.xls格式的文件")
        
        # 确保文件目录存在
        upload_dir = "static/files"
        os.makedirs(upload_dir, exist_ok=True)
        
        # 生成唯一文件名
        file_extension = os.path.splitext(file.filename)[1]
        unique_filename = f"{file.filename.split('.')[0]}_{random.randint(1000, 9999)}{file_extension}"
        file_path = os.path.join(upload_dir, unique_filename)
        
        # 保存上传的文件
        contents = await file.read()
        with open(file_path, "wb") as f:
            f.write(contents)
        
        try:
            # 读取Excel文件中的所有表名
            excel_file = pd.ExcelFile(file_path)
            sheet_names = excel_file.sheet_names
            
            # 读取每个表的预览数据
            sheets_data = {}
            for sheet_name in sheet_names:
                # 只读取前5行作为预览
                df = excel_file.parse(sheet_name, nrows=5)
                sheets_data[sheet_name] = df.fillna('').to_dict(orient='records')
            
            return JSONResponse(
                content={
                    "message": "Excel文件上传成功",
                    "filename": file.filename,
                    "saved_path": file_path,
                    "sheets": sheet_names,
                    "preview_data": sheets_data
                },
                status_code=200
            )
        except Exception as e:
            # 如果解析失败，删除已上传的文件
            if os.path.exists(file_path):
                os.remove(file_path)
            raise e
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"处理Excel文件失败: {str(e)}")

@router_html_real.post("/read_excel_sheet")
async def read_excel_sheet(file: UploadFile = File(...), sheet_name: str = Form(...)):
    """读取指定Excel文件的特定表格内容"""
    try:
        # 检查文件类型
        if not file.filename.endswith(('.xlsx', '.xls')):
            raise HTTPException(status_code=400, detail="只接受.xlsx或.xls格式的文件")
        
        # 确保文件目录存在
        upload_dir = "static/files"
        os.makedirs(upload_dir, exist_ok=True)
        
        # 生成唯一文件名并保存
        file_extension = os.path.splitext(file.filename)[1]
        unique_filename = f"{file.filename.split('.')[0]}_{random.randint(1000, 9999)}{file_extension}"
        file_path = os.path.join(upload_dir, unique_filename)
        
        # 保存上传的文件
        contents = await file.read()
        with open(file_path, "wb") as f:
            f.write(contents)
        
        try:
            # 读取指定表格的内容
            df = pd.read_excel(file_path, sheet_name=sheet_name)
            
            # 将数据转换为列表格式
            data = df.fillna('').values.tolist()
            headers = df.columns.tolist()
            
            # 删除临时文件
            if os.path.exists(file_path):
                os.remove(file_path)
            
            return JSONResponse(
                content={
                    "message": "表格数据读取成功",
                    "filename": file.filename,
                    "sheet_name": sheet_name,
                    "headers": headers,
                    "data": data
                },
                status_code=200
            )
        except Exception as e:
            # 确保临时文件被删除
            if os.path.exists(file_path):
                os.remove(file_path)
            raise e
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"读取Excel表格失败: {str(e)}")
